package com.zhs.gccs.view.taskMap;

import static com.mapbox.maps.extension.style.expressions.generated.Expression.literal;

import android.content.Context;
import android.graphics.Bitmap;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.View;
import android.view.WindowManager;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.annimon.stream.Stream;
import com.baidu.location.BDAbstractLocationListener;
import com.baidu.location.BDLocation;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.mapbox.android.gestures.MoveGestureDetector;
import com.mapbox.android.gestures.RotateGestureDetector;
import com.mapbox.android.gestures.StandardScaleGestureDetector;
import com.mapbox.bindgen.Expected;
import com.mapbox.bindgen.None;
import com.mapbox.geojson.Feature;
import com.mapbox.geojson.FeatureCollection;
import com.mapbox.geojson.Point;
import com.mapbox.maps.AsyncOperationResultCallback;
import com.mapbox.maps.CameraBounds;
import com.mapbox.maps.CameraOptions;
import com.mapbox.maps.CameraState;
import com.mapbox.maps.EdgeInsets;
import com.mapbox.maps.MapView;
import com.mapbox.maps.MapboxMap;
import com.mapbox.maps.QueriedFeature;
import com.mapbox.maps.RenderedQueryGeometry;
import com.mapbox.maps.RenderedQueryOptions;
import com.mapbox.maps.ScreenCoordinate;
import com.mapbox.maps.Style;
import com.mapbox.maps.ViewAnnotationOptions;
import com.mapbox.maps.extension.observable.eventdata.CameraChangedEventData;
import com.mapbox.maps.extension.observable.eventdata.MapLoadingErrorEventData;
import com.mapbox.maps.extension.style.expressions.generated.Expression;
import com.mapbox.maps.extension.style.layers.Layer;
import com.mapbox.maps.extension.style.layers.LayerUtils;
import com.mapbox.maps.extension.style.layers.generated.CircleLayer;
import com.mapbox.maps.extension.style.layers.generated.FillLayer;
import com.mapbox.maps.extension.style.layers.generated.LineLayer;
import com.mapbox.maps.extension.style.layers.generated.RasterLayer;
import com.mapbox.maps.extension.style.layers.generated.SymbolLayer;
import com.mapbox.maps.extension.style.layers.properties.generated.LineCap;
import com.mapbox.maps.extension.style.layers.properties.generated.LineJoin;
import com.mapbox.maps.extension.style.layers.properties.generated.Visibility;
import com.mapbox.maps.extension.style.sources.Source;
import com.mapbox.maps.extension.style.sources.SourceUtils;
import com.mapbox.maps.extension.style.sources.TileSet;
import com.mapbox.maps.extension.style.sources.generated.GeoJsonSource;
import com.mapbox.maps.extension.style.sources.generated.RasterSource;
import com.mapbox.maps.extension.style.sources.generated.VectorSource;
import com.mapbox.maps.plugin.Plugin;
import com.mapbox.maps.plugin.animation.CameraAnimationsPlugin;
import com.mapbox.maps.plugin.animation.MapAnimationOptions;
import com.mapbox.maps.plugin.attribution.AttributionPlugin;
import com.mapbox.maps.plugin.compass.CompassPlugin;
import com.mapbox.maps.plugin.compass.OnCompassClickListener;
import com.mapbox.maps.plugin.delegates.listeners.OnCameraChangeListener;
import com.mapbox.maps.plugin.delegates.listeners.OnMapLoadErrorListener;
import com.mapbox.maps.plugin.gestures.GesturesPlugin;
import com.mapbox.maps.plugin.gestures.GesturesUtils;
import com.mapbox.maps.plugin.gestures.OnMapClickListener;
import com.mapbox.maps.plugin.gestures.OnMoveListener;
import com.mapbox.maps.plugin.gestures.OnRotateListener;
import com.mapbox.maps.plugin.gestures.OnScaleListener;
import com.mapbox.maps.plugin.locationcomponent.LocationComponentPlugin;
import com.mapbox.maps.plugin.locationcomponent.generated.LocationComponentSettings;
import com.mapbox.maps.plugin.logo.LogoPlugin;
import com.mapbox.maps.plugin.scalebar.ScaleBarPlugin;
import com.mapbox.maps.viewannotation.ViewAnnotationManager;
import com.mapbox.turf.TurfMeasurement;
import com.wwren.ucrop.util.ScreenUtils;
import com.zhs.gccs.R;
import com.zhs.gccs.mbtiles.LayerConstant;
import com.zhs.gccs.mbtiles.MapLayer;
import com.zhs.gccs.mbtiles.MapLayerLayout;
import com.zhs.gccs.mbtiles.MapSource;
import com.zhs.gccs.model.SensorData;
import com.zhs.gccs.view.BaseView;
import com.zhs.gccs.view.LocationAddress;
import com.zhs.gccs.utils.FileUtils;
import com.zhs.gccs.utils.GPSUtils;
import com.zhs.gccs.utils.Utils;

import org.greenrobot.greendao.annotation.NotNull;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import kotlin.Unit;
import kotlin.jvm.functions.Function1;

//https://blog.csdn.net/sinat_41310868/article/details/115467830
//https://blog.csdn.net/CHENEY0314/article/details/124220421
//https://blog.csdn.net/GISuuser/article/details/103405764
//pbf 问题 https://blog.csdn.net/sinat_41310868/article/details/115467830
//mbtiles https://gist.github.com/typebrook/7d25be326f0e9afd58e0bbc333d2a175
public class MapBoxView extends BaseView {
    private MapView mapView;
    //    private TextView tv_compass;
    private MapScaleView mapScaleView;
    private MapboxMap mMapboxMap;
    private CameraBounds boundsDefault;
    private Style mapboxStyle;
    private CameraAnimationsPlugin cameraAnimationsPlugin;
    public static final double DEFAULT_ZOOM_OF_PROJECT = 14.0;
    public static final double DEFAULT_ZOOM_OF_LOCATION = 18.0;
    private static final double DEFAULT_ZOOM_VALUE = 12.0;   // 初始地图缩放大小
    private LocationClient mBaiduLocationClient;
    //声明mlocationClient对象
//    public AMapLocationClient mGaodeLocationClient;
    //声明mLocationOption对象
//    public AMapLocationClientOption mLocationOption = null;
    //https://blog.51cto.com/u_16213333/7818045
    private SensorManager sensorManager;
    SensorEventListener sensorEventListener;
    private SensorData sensorData;
    private double mapboxBearing = 0;//地图倾斜角
    private boolean isDriving = false;//是否在导航
    private List<MapSource> mapSources;
    private Point pointOfLast;//最近一次定位
    private String DEFAULT_MAP_STYLE = Style.SATELLITE_STREETS;
    private double zoom = DEFAULT_ZOOM_VALUE;
    private Point pointOfCenter;
    //导航相关
    private ViewAnnotationManager viewAnnotationManager;

//    private boolean userChangeMapRotate = false;//地图在旋转
    private OnMapMoveListener onMapMoveListener;
    private MapBoxMarkerAddListener mapBoxMarkerAddListener;
    private List<MapBoxCameraChangedListener> cameraChangedListeners;
    private MapBoxViewListener mapBoxViewListener;
    ////////////////////////////////////////////////////////////////
    public MapBoxView(@NonNull Context context) {
        super(context);
    }
    public MapBoxView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }
    public MapBoxView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    ////////////////////////////////////////////////////////////////
    @Override
    public void init(Context context, AttributeSet attrs, int defStyleAttr) {
        View view = LayoutInflater.from(context).inflate(R.layout.layout_mapbox_view, this, true);
//        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomerLogo);
//        String title = typedArray.getString(R.styleable.CustomerInfoItem_preText);
//        typedArray.recycle();
        mapView = findViewById(R.id.mapView);
//        tv_compass = findViewById(R.id.tv_compass);
        mapScaleView = findViewById(R.id.mapScaleView);
        mMapboxMap = mapView.getMapboxMap();
    }

    public void onDestroy(){
        if(mBaiduLocationClient !=null) {
            mBaiduLocationClient.stop();
        }
//        if(mGaodeLocationClient!=null){
//            mGaodeLocationClient.stopLocation();
//            mGaodeLocationClient.onDestroy();
//        }
        if(sensorManager!=null&&sensorEventListener!=null){
            sensorManager.unregisterListener(sensorEventListener);
        }
        mMapboxMap.clearData(new AsyncOperationResultCallback() {
            @Override
            public void run(@NonNull Expected<String, None> result) {

            }
        });
        mapView.onDestroy();
    }

    ////////////////////////////////////////////////////////////////////////////
    public void loadOnlineStyle() {
        mMapboxMap.loadStyleUri(DEFAULT_MAP_STYLE, new Style.OnStyleLoaded() {
            @Override
            public void onStyleLoaded(@NonNull Style style) {
                mapboxStyle = style;
                if (mapBoxViewListener != null) mapBoxViewListener.onMapStyleLoaded(mapboxStyle);
            }
        }, new OnMapLoadErrorListener() {
            @Override
            public void onMapLoadError(@NonNull MapLoadingErrorEventData error) {
                Log.d("mapbox", "onMapLoadError of " + error.getSourceId());
//                ToastUtils.toast("地图加载失败");
            }
        });
    }
    public void loadLocalStyle() {
        //参考：https://blog.csdn.net/weixin_44402694/article/details/125415572
        //mapboxMap.setStyle(new Style.Builder().fromUri("https://www.mapbox.com/android-docs/files/mapbox-raster-v8.json"));//satellite-streets-v11
        // mapboxMap.setStyle(new Style.Builder().fromUri("asset://local_style_file.json"));
        mMapboxMap.loadStyleUri("asset://map/local_style_file_mapbox.json", new Style.OnStyleLoaded() {
            @Override
            public void onStyleLoaded(@NonNull Style style) {
                mapboxStyle = style;
                if (mapBoxViewListener != null) mapBoxViewListener.onMapStyleLoaded(mapboxStyle);
            }
        });
    }
    ////////////////////////////////////////////////////////////////////////////
    public void load(List<MapSource> data) {
        mapSources = new ArrayList<>();
        if (data != null) mapSources.addAll(data);
        for (MapSource mapSource : mapSources) {
            addMapSource(mapSource);
        }
    }
    private void addMapSource(MapSource mapSource) {
        try {
            //先移除，然后重新添加
            if (mapSource.getLayers() != null) {
                Stream.of(mapSource.getLayers()).forEach(item -> {
                    String layerId = item.getLayerId();
                    Layer layer = LayerUtils.getLayer(mapboxStyle, layerId);
                    if (layer != null) {
                        mapboxStyle.removeStyleLayer(layerId);
                    }
                });
                Source source = SourceUtils.getSource(mapboxStyle, mapSource.getSourceId());
                if (source != null) {
                    mapboxStyle.removeStyleSource(mapSource.getSourceId());
                }
            }
            if (MapSource.type_vector.equals(mapSource.getType())) {
                addVectorSourceLayer(mapSource);
            } else if (MapSource.type_raster.equals(mapSource.getType())) {
                addRasterSourceLayer(mapSource);
            } else if (MapSource.type_geojson.equals(mapSource.getType())) {
                addGsonLayer(mapSource);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void mapboxInitConfig() {
        configMapboxEvent();
        configMapboxLanguage();
        //定位初始化
        initBaiduLocation();
        initSensor();
    }
    private void configMapboxEvent() {
        viewAnnotationManager = mapView.getViewAnnotationManager();
        //参考：https://blog.csdn.net/CHENEY0314/article/details/124220421
        //1. 地图 Logo 插件
        LogoPlugin logoPlugin = mapView.getPlugin(Plugin.MAPBOX_LOGO_PLUGIN_ID);
        // 隐藏 Logo
        if (logoPlugin != null) {
            logoPlugin.setEnabled(false);
        }
        //2. 地图Logo旁属性按钮插件
        AttributionPlugin attributionPlugin = mapView.getPlugin(Plugin.MAPBOX_ATTRIBUTION_PLUGIN_ID);
        // 隐藏 属性按钮
        if (attributionPlugin != null) {
            attributionPlugin.setEnabled(false);
        }
        //3. 比例尺Scalebar插件
        ScaleBarPlugin scaleBarPlugin = mapView.getPlugin(Plugin.MAPBOX_SCALEBAR_PLUGIN_ID);
        // 隐藏 比例尺
        if (scaleBarPlugin != null) {
            scaleBarPlugin.setEnabled(false);
            scaleBarPlugin.setMarginBottom(ScreenUtils.dip2px(context, 15));
            scaleBarPlugin.setPosition(Gravity.START | Gravity.BOTTOM);
        }
        //4. 指南针插件
        CompassPlugin compassPlugin = mapView.getPlugin(Plugin.MAPBOX_COMPASS_PLUGIN_ID);
        if (compassPlugin != null) {
            compassPlugin.setEnabled(false);    // 隐藏指南针
            //compassPlugin.setImage(drawable);	// 更换指南针icon
            compassPlugin.addCompassClickListener(new OnCompassClickListener() {
                @Override
                public void onCompassClick() {
//                    userChangeMapRotate = false;
                }
            });
        }
        //5相机位置改变：
        cameraAnimationsPlugin = mapView.getPlugin(Plugin.MAPBOX_CAMERA_PLUGIN_ID);
        ////6. 用户地理位置获取插件
        LocationComponentPlugin locationPlugin = mapView.
                getPlugin(Plugin.MAPBOX_LOCATION_COMPONENT_PLUGIN_ID);
//        设置用户位置点显示UI样式：
//        设置脉冲显示效果：
        locationPlugin.updateSettings(new Function1<LocationComponentSettings, Unit>() {
            @Override
            public Unit invoke(LocationComponentSettings locationComponentSettings) {
                locationComponentSettings.setEnabled(false);
                locationComponentSettings.setPulsingEnabled(false);  // 脉冲效果
                return null;
            }
        });
        mapView.getMapboxMap().addOnCameraChangeListener(new OnCameraChangeListener() {
            @Override
            public void onCameraChanged(@NonNull CameraChangedEventData cameraChangedEventData) {
                if (isDriving) return;
                CameraState cameraState = mapView.getMapboxMap().getCameraState();
                zoom = cameraState.getZoom();
                pointOfCenter = cameraState.getCenter();
                if (mapBoxViewListener != null) mapBoxViewListener.onZoomChange((int) zoom);
                if (cameraChangedListeners != null) {
                    for (MapBoxCameraChangedListener listener : cameraChangedListeners) {
                        listener.onCameraChanged();
                    }
                }
                mapScaleView.refreshScaleView(mapView.getMapboxMap());
//                Log.d("mapbox", "onCameraChanged");
            }
        });
        ///移动 start move ---> move ---> onCameraChanged --->move --->onCameraChanged  --->moveed
        //所以如果不需要那么细致的条件判定，可以不用设置 OnMoveListener 可以直接用 onCameraChanged获取中心位置
        //7. 地图手势监听插件
        //可以监听地图相关运行中状态，Mapbox提供了手势插件供我们监听各种地图状态：
        GesturesPlugin gesturesPlugin = mapView.getPlugin(Plugin.MAPBOX_GESTURES_PLUGIN_ID);
        // 地图移动监听
        OnMoveListener onMoveListener = new OnMoveListener() {
            @Override
            public void onMoveBegin(@NotNull MoveGestureDetector moveGestureDetector) {
                if (isDriving) return;
                // 地图开始移动
                CameraState cameraState = mapView.getMapboxMap().getCameraState();
                if (onMapMoveListener != null)
                    onMapMoveListener.onMoveStart((int) cameraState.getZoom(), cameraState.getCenter());
            }

            @Override
            public boolean onMove(@NotNull MoveGestureDetector moveGestureDetector) {
                CameraState cameraState = mapView.getMapboxMap().getCameraState();
                if (onMapMoveListener != null) onMapMoveListener.onMove((int) cameraState.getZoom(),
                        cameraState.getCenter());
                return false;
            }

            @Override
            public void onMoveEnd(@NotNull MoveGestureDetector moveGestureDetector) {
                if (isDriving) return;
                CameraState cameraState = mapView.getMapboxMap().getCameraState();
                if (onMapMoveListener != null)
                    onMapMoveListener.onMoveEnd((int) cameraState.getZoom(), cameraState.getCenter());
            }
        };

        //https://blog.csdn.net/Mr_theSun/article/details/107609939
        if (gesturesPlugin != null) {
            gesturesPlugin.addOnMoveListener(onMoveListener);    // 注意onDestroy时要remove掉Listener
            gesturesPlugin.addOnScaleListener(new OnScaleListener() {
                @Override
                public void onScaleBegin(@NonNull StandardScaleGestureDetector standardScaleGestureDetector) {
//                    Log.d("mapbox", "onScaleBegin");
                }

                @Override
                public void onScale(@NonNull StandardScaleGestureDetector standardScaleGestureDetector) {
//                    Log.d("mapbox", "onScale");
                    zoom = mapView.getMapboxMap().getCameraState().getZoom();
                    if (mapBoxViewListener != null) mapBoxViewListener.onZoomChange((int) zoom);
                }

                @Override
                public void onScaleEnd(@NonNull StandardScaleGestureDetector standardScaleGestureDetector) {
//                    Log.d("mapbox", "onScaleEnd");
                    zoom = mapView.getMapboxMap().getCameraState().getZoom();
                    if (mapBoxViewListener != null) mapBoxViewListener.onZoomChange((int) zoom);
                }
            });
            //gesturesPlugin.addOnMapClickListener(); 或者用 GesturesUtils
            GesturesUtils.addOnMapClickListener(mapView.getMapboxMap(), new OnMapClickListener() {
                @Override
                public boolean onMapClick(@NonNull Point point) {
                    if (mapSources == null || mapSources.size() == 0) return false;
                    zoom = mapView.getMapboxMap().getCameraState().getZoom();
                    if (mapBoxViewListener != null) mapBoxViewListener.onZoomChange((int) zoom);
                    if (mapBoxViewListener != null) mapBoxViewListener.onMapClicked(point);
                    return true;
                }
            });
            gesturesPlugin.setRotateEnabled(true);//
            GesturesUtils.addOnRotateListener(mapView.getMapboxMap(), new OnRotateListener() {
                @Override
                public void onRotateBegin(@NonNull RotateGestureDetector rotateGestureDetector) {
//                    userChangeMapRotate = true;
                    double bearing = mapView.getMapboxMap().getCameraState().getBearing();
                    Log.i("onRotateStart",bearing+"-------user angle-------"+sensorData.getAngle());
//                    if(sensorData!=null){
//                        bearing(sensorData.getAngle());
//                    }
                }

                @Override
                public void onRotate(@NonNull RotateGestureDetector rotateGestureDetector) {
//                    float angleThreshold = rotateGestureDetector.getAngleThreshold();
//                    assert compassPlugin != null;
                    double bearing = mapView.getMapboxMap().getCameraState().getBearing();
                    Log.i("onRotate",bearing+"-------user angle-------"+sensorData.getAngle());
//                     (-(int) bearing);
//                    if(sensorData!=null){
//                        bearing(sensorData.getAngle());
//                    }
                    double angle = 360-bearing;
                    mapboxBearing = angle;
                    updateUserLocationMarkerRotate();
                }

                @Override
                public void onRotateEnd(@NonNull RotateGestureDetector rotateGestureDetector) {
                    double bearing = mapView.getMapboxMap().getCameraState().getBearing();
                    double angle = 360-bearing;
                    mapboxBearing = angle;
                    updateUserLocationMarkerRotate();
                    Log.i("onRotateEnd",bearing+"-------user angle-------"+sensorData.getAngle());
//                    userChangeMapRotate = false;
//                    int angle = (int) (Math.round(bearing) + 90);
//                    updateUserLocationMarkerRotate(-(int) bearing);
//                    if(sensorData!=null){
//                        bearing(sensorData.getAngle());
//                    }
                }
            });
        }
        //https://www.jianshu.com/p/c9e4aede26e2
        //本地化
        //https://docs.mapbox.com/android/legacy/plugins/examples/change-map-text-to-device-language/
//        LocalizationPlugin localizationPlugin = new LocalizationPlugin(mapView,mMapboxMap,mapboxStyle);
//        localizationPlugin.matchMapLanguageWithDeviceDefault();
    }
    //中文
    private void configMapboxLanguage() {
        //mapbox默认的style加载了很多图层，
        // 参考文档：https://docs.mapbox.com/data/tilesets/reference/mapbox-streets-v8/
//        SymbolLayer countryLabelTextSymbolLayer = mapboxStyle.getLayerAs("country-label");
//        SymbolLayer layer = (SymbolLayer) LayerUtils.getLayer(mapboxStyle, "country-label");
//        if (layer != null) {
//            layer.textField("{name_zh-Hans}");
//        }
        Stream.of(mapboxStyle.getStyleLayers())
                .filter(i -> i.getId().contains("label"))
                .forEach(item -> {
                    SymbolLayer layer = (SymbolLayer) LayerUtils.getLayer(mapboxStyle, item.getId());
                    if (layer != null) {
                        layer.textField("{name_zh-Hans}");
                    }
                });
    }

    private void initBaiduLocation() {
        try {
            //百度地图发布https://lbs.baidu.com/index.php?title=android-privacy
            LocationClient.setAgreePrivacy(true);
            mBaiduLocationClient = new LocationClient(context);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //通过LocationClientOption设置LocationClient相关参数
        LocationClientOption option = new LocationClientOption();
        option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
        option.setOpenGps(true); // 打开gps
        option.setCoorType("gcj02"); // 设置坐标类型---mapbox
        option.setScanSpan(1000);
        option.setNeedDeviceDirect(true);
        option.setIsNeedAddress(true); // 可选，设置是否需要地址信息，默认不需要
        option.setIsNeedLocationDescribe(true); // 可选，设置是否需要地址描述
        option.setLocationNotify(false); // 可选，默认false，设置是否当gps有效时按照1S1次频率输出GPS结果
        option.setIgnoreKillProcess(true); // 可选，默认true，定位SDK内部是一个SERVICE，并放到了独立进程，设置是否在stop
        option.setIsNeedLocationDescribe(true); // 可选，默认false，设置是否需要位置语义化结果，可以在BDLocation
        option.setIsNeedLocationPoiList(true); // 可选，默认false，设置是否需要POI结果，可以在BDLocation
        option.SetIgnoreCacheException(false); // 可选，默认false，设置是否收集CRASH信息，默认收集
        option.setIsNeedAltitude(true); // 可选，默认false，设置定位时是否需要海拔信息，默认不需要，除基础定位版本都可用
        //设置locationClientOption
        mBaiduLocationClient.setLocOption(option);
        mBaiduLocationClient.registerLocationListener(new BDAbstractLocationListener() {
            @Override
            public void onReceiveLocation(BDLocation bdLocation) {
                if (isDriving) return;
//                LogUtils.e("bdLocation = " + bdLocation.toString());
                //mapView 销毁后不在处理新接收的位置
                if (bdLocation == null || mapView == null || TextUtils.isEmpty(bdLocation.getAddrStr())) {
//                    ToastUtils.toast("定位异常");
//                    mBaiduLocationClient.stop();
                    //initGdLocation();
                    return;
                }
                //百度的坐标转为mabox的坐标
//                if (mapBoxViewListener != null) mapBoxViewListener.onZoomChange((int) zoom);
                //bdLocation.getAdCode() bdLocation.getDirection()  bdLocation.getAddress()   bdLocation.getCity()
                double[] doubles2 = GPSUtils.gcj02towgs84(bdLocation.getLongitude(), bdLocation.getLatitude());
                Point p = Point.fromLngLat(doubles2[0], doubles2[1]);
                LocationAddress location = new LocationAddress(doubles2[0], doubles2[1],
                        bdLocation.getProvince(), bdLocation.getCity(), bdLocation.getDistrict(),
                        bdLocation.getTown(), bdLocation.getStreet());
                location.setAddress(bdLocation.getAddrStr());
                updateUserLocationPointData(p, location);
            }
        });
        //开启地图定位图层
        mBaiduLocationClient.start();
    }
    private void updateUserLocationPointData(Point p, LocationAddress location) {
        double distance = 0;//走动10m，需要移动
        if (pointOfLast != null) {
            distance = TurfMeasurement.distance(pointOfLast, p) * 1000;//TurfMeasurement.distance 返回的是千米
        }
//        if (pointOfLaste == null || distance >= 5) {//5m
//            pointOfLaste = p;//北京 116.322292   39.960648
//            //将地图中心移动到用户位置处
//            Point center = mapView.getMapboxMap().getCameraState().getCenter();
//            double distanceOfCenter = TurfMeasurement.distance(pointOfLaste, center) * 1000;
//            double zoom = mapView.getMapboxMap().getCameraState().getZoom();
//            if (distanceOfCenter > 1000) {
//                moveCameraTo(pointOfLaste, 1000);
//            }
//            if (mapBoxViewListener != null) mapBoxViewListener.onLocationChange(location);
//            //更新用户图层
//            updateUserLocationMarkerPosition(p);
//        }
        pointOfLast = p;
        Point center = mapView.getMapboxMap().getCameraState().getCenter();
        double distanceOfCenter = TurfMeasurement.distance(pointOfLast, center) * 1000;
        if (distanceOfCenter > 1000) {//移动1公里后把地图中心移动到当前位置
//            moveCameraTo(pointOfLaste, 1000);
        }
        if (mapBoxViewListener != null) mapBoxViewListener.onLocationChange(location);
        //更新用户图层
        updateUserLocationMarkerPosition(p);
    }
    private void initGdLocation() {
        try {
            AMapLocationClient mGaodeLocationClient = new AMapLocationClient(context);
            //初始化定位参数
            AMapLocationClientOption mLocationOption = new AMapLocationClientOption();
            //设置定位监听
            mGaodeLocationClient.setLocationListener(new AMapLocationListener() {
                @Override
                public void onLocationChanged(AMapLocation amapLocation) {
                    if (amapLocation != null) {
                        if (amapLocation.getErrorCode() == 0) {
                            float speed = amapLocation.getSpeed();//速度  单位：米/秒
                            float bearing = amapLocation.getBearing();//获取方向角信息
                            int gpsAccuracyStatus = amapLocation.getGpsAccuracyStatus();//获取GPS当前状态，返回值可参考AMapLocation类提供的常量
                            //定位成功回调信息，设置相关消息
                            //                        amapLocation.getLocationType();//获取当前定位结果来源，如网络定位结果，详见定位类型表
                            //                        amapLocation.getLatitude();//获取纬度
                            //                        amapLocation.getLongitude();//获取经度
                            //                        amapLocation.getAccuracy();//获取精度信息
                            double[] doubles2 = GPSUtils.gcj02towgs84(amapLocation.getLongitude(), amapLocation.getLatitude());
                            Point p = Point.fromLngLat(doubles2[0], doubles2[1]);
                            LocationAddress location = new LocationAddress(doubles2[0], doubles2[1],
                                    amapLocation.getProvince(), amapLocation.getCity(), amapLocation.getDistrict(),
                                    amapLocation.getStreet(), amapLocation.getStreet());
                            location.setAddress(amapLocation.getAddress());
                            updateUserLocationPointData(p, location);
                        } else {
                            //显示错误信息ErrCode是错误码，errInfo是错误信息，详见错误码表。
                            Log.e("AmapError", "location Error, ErrCode:"
                                    + amapLocation.getErrorCode() + ", errInfo:"
                                    + amapLocation.getErrorInfo());
                        }
                    }
                }
            });
            //设置定位模式为Hight_Accuracy高精度模式，Battery_Saving为低功耗模式，Device_Sensors是仅设备模式
            mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
            //设置定位间隔,单位毫秒,默认为2000ms
            mLocationOption.setInterval(2000);
            //设置定位模式为AMapLocationMode.Device_Sensors，仅设备模式。
//            mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Device_Sensors);
            //设置定位参数
            mGaodeLocationClient.setLocationOption(mLocationOption);
            // 此方法为每隔固定时间会发起一次定位请求，为了减少电量消耗或网络流量消耗，
            // 注意设置合适的定位时间的间隔（最小间隔支持为1000ms），并且在合适时间调用stopLocation()方法来取消定位请求
            // 在定位结束后，在合适的生命周期调用onDestroy()方法
            // 在单次定位情况下，定位无论成功与否，都无需调用stopLocation()方法移除请求，定位sdk内部会移除
            //启动定位
            mGaodeLocationClient.startLocation();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //////////////////////////////////////////////////////////////////
    public void queryMapPointFeatures(Point point, MapBoxQueryListener mapBoxQueryListener) {
        ScreenCoordinate clicked = mapView.getMapboxMap().pixelForCoordinate(point);
        List<String> layers = Stream.of(mapSources).flatMap(item -> Stream.of(item.getLayers()))
                .map(item -> item.getLayerId()).filter(item -> {
                    Layer layer = LayerUtils.getLayer(mapboxStyle, item);
                    return layer != null && layer.getVisibility() == Visibility.VISIBLE;
                }).toList();
//                    new RenderedQueryGeometry(new ScreenBox(
//                            new ScreenCoordinate(clicked.getX() - 50, clicked.getY() - 50),
//                            new ScreenCoordinate(clicked.getX() + 50, clicked.getY() + 50)
//                    )),
        mMapboxMap.queryRenderedFeatures(
                new RenderedQueryGeometry(clicked),
                new RenderedQueryOptions(layers, literal(true)), features -> {
                    List<QueriedFeature> featureList = features.getValue();
//                    if(featureList!=null&&featureList.size()>0&&mapBoxQueryListener!=null){
                    mapBoxQueryListener.onQuery(featureList);
//                    }
                });
    }
    private int axis_x;
    private int axis_y;
    //////////////////////////////////////////////////
    private void initSensor() {
        // 根据当前上下文的屏幕方向调整与自然方向的相对关系。
        // 当设备的自然方向是竖直方向（比如，理论上说所有手机的自然方向都是都是是竖直方向），而应用是横屏时，
        // 需要将相对设备自然方向的方位角转换为相对水平方向的方位角。

        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        Display dis = wm.getDefaultDisplay();
        int rotation = dis.getRotation();

        axis_x = SensorManager.AXIS_X;
        axis_y = SensorManager.AXIS_Y;
        switch (rotation) {
            case Surface.ROTATION_0:
                break;
            case Surface.ROTATION_90:
                axis_x = SensorManager.AXIS_Y;
                axis_y = SensorManager.AXIS_MINUS_X;
                break;
            case Surface.ROTATION_180:
                axis_x = SensorManager.AXIS_X;
                axis_y = SensorManager.AXIS_MINUS_Y;
                break;
            case Surface.ROTATION_270:
                axis_x = SensorManager.AXIS_MINUS_Y;
                axis_y = SensorManager.AXIS_X;
                break;
            default:
                break;
        }
//        Vibrator mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
        // 实例化传感器管理者
        sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
        // 初始化加速度传感器
        Sensor mAccelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
//        Sensor.TYPE_ACCELEROMETER：加速度传感器
//        Sensor.TYPE_GYROSCOPE：陀螺仪传感器
//        Sensor.TYPE_LIGHT：光传感器
//        Sensor.TYPE_PROXIMITY：距离传感器
//        Sensor.TYPE_MAGNETIC_FIELD：磁力计传感器
        // 初始化地磁场传感器
        Sensor mMagneticFieldSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
//        Sensor mGyroscopeSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
//        sensorEventListener = new SensorEventListener() {
//            int mAngle = 0; // 角度 传值mapbox
//            String angleStr;
//            String sensorDegree = "";
//            DecimalFormat df = new DecimalFormat("0.00");
//            private float[] accelerometerValues = new float[3];
//            private float[] magneticFieldValues = new float[3];
//
//            @Override
//            public void onSensorChanged(SensorEvent event) {
//                if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
////                    accelerometerValues = event.values;
//                    //赋值调用clone方法
//                    accelerometerValues = event.values.clone();
//                    //https://blog.csdn.net/weixin_37969624/article/details/126659300
//                    calculateOrientation();
//                }
//                if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
//                    magneticFieldValues = event.values;
//                }
//            }
//            private void calculateOrientation() {
//                float[] rotate = new float[9];
//                float[] I = new float[9];
//                float[] values = new float[3];
//                boolean success = SensorManager.
//                        getRotationMatrix(rotate, I, accelerometerValues, magneticFieldValues);
////                sensorManager.getOrientation(rotate, values);
//                // 根据当前上下文的屏幕方向调整与自然方向的相对关系。
//                // 当设备的自然方向是竖直方向（比如，理论上说所有手机的自然方向都是都是是竖直方向，而有些平板的自然方向是水平方向），而应用是横屏时，
//                // 需要将相对设备自然方向的方位角转换为相对水平方向的方位角。
//                float[] rotateOut = new float[9];
//                SensorManager.remapCoordinateSystem(rotate, axis_x, axis_y, rotateOut);
//                sensorManager.getOrientation(rotateOut, values);
//                //【2.2】根据inclination matrix计算磁仰角，地球表面任一点的地磁场总强度的矢量方向与水平面的夹角。
////                double mInclination = SensorManager.getInclination(I);
//                //Log.i(TAG, "onSensorChanged: -----磁场强度："+henceValue);
//                //Log.d("Main","values[0] :"+Math.toDegrees(values[0]));
//                //values[0]的取值范围是-180到180度。
//                //将计算出的旋转角度取反，用于旋转指南针背景图
//                //+-180表示正南方向，0度表示正北，-90表示正西，+90表示正东
//                ////此结果为从北到南顺时针为0-180度，从南-北顺指针-180到0度，其实是弧度运算的，也就是从北顺指针是0-360度
//                int mAzimuth = (int) Math.toDegrees(values[0]);
//                int valueNew1;
////                int valueNew = (mAzimuth + 90 + 360) % 360;
//                if (mAzimuth<0) {
//                    mAzimuth=mAzimuth+360;
//                }
////                int valueNew = (mAzimuth  + 360) % 360;//
//                int valueNew = mAzimuth;//
//                Log.i("calculateOrientation","----"+mAzimuth+"----"+valueNew);
//                if (valueNew >= 350 || valueNew < 10) {
////                    tvSensor.setText("正北" + df.format(Math.abs(values[0])) + "°");
//                    angleStr = "正北";
//                } else if (valueNew >= 10 && valueNew < 80) {
////                    tvSensor.setText("东北" + df.format(Math.abs(values[0])) + "°");
//                    angleStr = "东北";
//                } else if (valueNew >= 80 && valueNew < 100) {
//                    angleStr = "正东";
//                } else if (valueNew >= 100 && valueNew < 170) {
//                    angleStr = "东南";
//                } else if (valueNew >= 170 && valueNew <= 190) {
//                    angleStr = "正南";
//                } else if (valueNew >= 190 && valueNew < 260) {
//                    angleStr = "西南";
//                } else if (valueNew >= 260 && valueNew <= 280) {
//                    angleStr = "正西";
//                } else if (valueNew >= 280 && valueNew < 350) {
////                    tvSensor.setText("西北" + df.format(Math.abs(values[0])) + "°");
//                    angleStr = "西北";
//                }
//                float SmoothFactorCompass = 0.90f;
//                float SmoothThresholdCompass = 5.0f;
//                //矫正，防止抖动
////                if (Math.abs(mAngle - valueNew) < 180) {
////                    if (Math.abs(mAngle - valueNew) > SmoothThresholdCompass) {
////                        valueNew1 = valueNew;
////                    } else {
////                        valueNew1 = (int) (mAngle + SmoothFactorCompass * (valueNew - mAngle));
////                    }
////                } else {
////                    if (360.0 - Math.abs(valueNew - mAngle) > SmoothThresholdCompass) {
////                        valueNew1 = valueNew;
////                    } else {
////                        if (mAngle > valueNew) {
////                            valueNew1 = (int) ((mAngle + SmoothFactorCompass * ((360 + valueNew - mAngle) % 360) + 360) % 360);
////                        } else {
////                            valueNew1 = (int) ((mAngle - SmoothFactorCompass * ((360 - valueNew + mAngle) % 360) + 360) % 360);
////                        }
////                    }
////                }
////                if (Math.abs(mAngle - valueNew) > SmoothThresholdCompass) {
////                    valueNew1 = valueNew;
////                } else {
////                    valueNew1 = (int) (mAngle + SmoothFactorCompass * (valueNew - mAngle));
////                }
//                valueNew1 = valueNew;
//                if (Math.abs(mAngle - valueNew1) >= 1 && success) {
////        if ( success) {
//                    mAngle = valueNew1;
////                    pitchNumber= (int) Math.toDegrees(values[1]);//俯仰角
////                    rollNumber= (int) Math.toDegrees(values[2]);//横滚角
////                    elevationNumber= (int) Math.toDegrees(mInclination);
////                    henceValue= (int)((I[3]*R[0]+I[4]*R[3]+I[5]*R[6])*magneticValues[0]+
////                            (I[3]*R[1]+I[4]*R[4]+I[5]*R[7])*magneticValues[1]+
////                            (I[3]*R[2]+I[4]*R[5]+I[5]*R[8])*magneticValues[2]);
//                    mAngle = Math.round(mAngle);//mapbox 需要增加90
//                    String tempDegree = df.format(Math.abs(mAngle)) + "";
//                    String tempSDegree = tempDegree.substring(0, tempDegree.indexOf("."));
//                    String tempDDegree = tempDegree.substring(tempDegree.indexOf(".") + 1, tempDegree.length());
//                    if (Integer.valueOf(tempSDegree) + 90 > 360) {
//                        sensorDegree = (Integer.valueOf(tempSDegree) + 90 - 360) + "." + tempDDegree + "°";
//                    } else {
//                        sensorDegree = Integer.valueOf(tempSDegree) + 90 + "." + tempDDegree + "°";
//                    }
//                    sensorData = new SensorData(mAngle, angleStr, sensorDegree);
////                    if (!userChangeMapRotate) {
////                        updateUserLocationMarkerRotate();
////                    }
//                    updateUserLocationMarkerRotate();
////                tv_compass.setText(angleStr+":"+mAngle);
//                    if (mapBoxViewListener != null)
//                        mapBoxViewListener.onSensorChanged(sensorData);
//                }
//            }
//
//            @Override
//            public void onAccuracyChanged(Sensor sensor, int accuracy) {
//                if (accuracy >= SensorManager.SENSOR_STATUS_ACCURACY_MEDIUM) {
//                    Log.e("Compass", " 不需要校验");
//                } else {
//                    ToastUtils.toast("角度精度过低，需要旋转手机校准");
//                }
//            }
//        };
////        sensorManager.registerListener(sensorEventListener, mSensorOrientation, SensorManager.SENSOR_DELAY_UI);
//        // 注册监听
//        if (mAccelerometerSensor != null) {
//            sensorManager.registerListener(sensorEventListener,
//                    mAccelerometerSensor, SensorManager.SENSOR_DELAY_UI);
////            sensorManager.registerListener(sensorEventListener,
////                    mAccelerometerSensor, SensorManager.SENSOR_DELAY_NORMAL);
//        }
//        if (mMagneticFieldSensor != null) {
//            sensorManager.registerListener(sensorEventListener, mMagneticFieldSensor,
//                    SensorManager.SENSOR_DELAY_UI);
////            sensorManager.registerListener(sensorEventListener, mMagneticFieldSensor,
////                    SensorManager.SENSOR_DELAY_NORMAL);
//        }
//        if(mGyroscopeSensor!=null){
//            sensorManager.registerListener(sensorEventListener, mGyroscopeSensor,
//                    SensorManager.SENSOR_DELAY_UI);
//        }

        Sensor mSensorOrientation = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
        SensorEventListener sensorEventListener = new SensorEventListener() {
            @Override
            public void onSensorChanged(SensorEvent event) {
                float azimuth = event.values[0];//SensorManager.DATA_X
                String direction = getDirection(-azimuth);
//                azimuth = (azimuth + 360) % 360;
                sensorData = new SensorData((int) azimuth, direction, azimuth+"");
                updateUserLocationMarkerRotate();
                if (mapBoxViewListener != null)
                        mapBoxViewListener.onSensorChanged(sensorData);
            }

            @Override
            public void onAccuracyChanged(Sensor sensor, int accuracy) {

            }
        };
        sensorManager.registerListener(sensorEventListener, mSensorOrientation, SensorManager.SENSOR_DELAY_GAME);
    }
    private String[] directions = {"北", "西北", "西", "西南", "南", "东南", "东", "东北" };
    private String getDirection(float azimuth) {
        azimuth = (azimuth + 360) % 360;
        int index = Math.round(azimuth / 45f) % 8;
        return directions[index];
    }
    //////////////////////////////////////////////////
    public void moveCameraTo(Point point, int duration) {
        double zoom = mMapboxMap.getCameraState().getZoom();
        double bearing = mMapboxMap.getCameraState().getBearing();
        moveCameraTo(point, zoom, bearing, duration);
    }
    public void moveCameraTo(Point point, int duration,double zoom) {
        double bearing = mMapboxMap.getCameraState().getBearing();
        moveCameraTo(point, zoom, bearing, duration);
    }

    public void moveCameraWithBearing(Point point, int duration,double bearing) {
        double zoom = mMapboxMap.getCameraState().getZoom();
        moveCameraTo(point, zoom, bearing, duration);
    }

    public void moveCameraTo(Point point, double zoom, double bearing, int duration) {
        if (mapView == null) {
            return;
        }
        if (point == null) {
            return;
        }
        if (duration != 0 && cameraAnimationsPlugin != null) {
            cameraAnimationsPlugin.flyTo(new CameraOptions.Builder()
                            .center(point)
                            .zoom(zoom)
                            .bearing(bearing)
                            .build(),
                    new MapAnimationOptions.Builder().duration(duration).build());
        } else {
            mMapboxMap.setCamera(new CameraOptions.Builder()
                    .center(point)
                    .zoom(zoom)
                    .bearing(bearing)
                    .build());

        }
        if (mapBoxViewListener != null) mapBoxViewListener.onMapCenterChanged(point);
    }

    public void zoomToChina() {
        Point point = Point.fromLngLat(104.1954, 35.8617);
        //{center:[104.1954,35.8617],zoom:3}
        this.zoom = 3;
//        this.userChangeMapRotate = false;
        this.mapboxBearing = 0d;
        mMapboxMap.setCamera(new CameraOptions.Builder()
                .center(point)
                .zoom(this.zoom)
                .bearing(mapboxBearing)//正北方向
                .build());
        if (boundsDefault != null) {
            boundsDefault = mMapboxMap.getBounds();
        }
        if (mapBoxViewListener != null) mapBoxViewListener.onMapCenterChanged(point);
    }

    public void fitBound(int zoom, double minx, double miny, double maxx, double maxy) {
//        CoordinateBounds bounds = new CoordinateBounds(southwest,northeast);
        this.zoom = zoom;
        Point center = Point.fromLngLat((minx + maxx) / 2.0,
                (miny + maxy) / 2.0);
        this.mapboxBearing = 0d;
        mMapboxMap.setCamera(new CameraOptions.Builder()
                .center(center)
                .zoom(this.zoom)
                .padding(new EdgeInsets(minx, maxy, maxx, miny))//
                .bearing(mapboxBearing)//正北方向
                .build());
        if (mapBoxViewListener != null) mapBoxViewListener.onMapCenterChanged(center);
    }

//    //设置旋转角度
//    public void bearing(int bearing){
//        mMapboxMap.setCamera(new CameraOptions.Builder()
//                .bearing((double) bearing)
//                .build());
//    }
    public void zoom(int zoom) {
        //缩放按钮点击后   onCameraChanged
        this.zoom = this.zoom + zoom;
        mMapboxMap.setCamera(new CameraOptions.Builder()
                .center(pointOfCenter)
                .zoom(this.zoom)
                .build());
        if (mapBoxViewListener != null) mapBoxViewListener.onMapCenterChanged(pointOfCenter);
    }

    public void locationToUser() {
        if (pointOfLast == null) return;
//        this.userChangeMapRotate = false;
        this.zoom = DEFAULT_ZOOM_OF_LOCATION;
        mapboxBearing = 0;
        mMapboxMap.setCamera(new CameraOptions.Builder()
                .center(pointOfLast)
                .zoom(this.zoom)
                .bearing(mapboxBearing)//正北方向
                .build());
        if (mapBoxViewListener != null) mapBoxViewListener.onMapCenterChanged(pointOfLast);
    }

    //////////////////////////////////////////////////
    public void setLayerVisible(boolean visible, String layerId) {
        if (TextUtils.isEmpty(layerId)) return;
        Layer layer = LayerUtils.getLayer(mapboxStyle, layerId);
        if (layer != null) {
            layer.visibility(visible ? Visibility.VISIBLE : Visibility.NONE);
        }
    }

    public void setLayerVisible(boolean visible, List<String> layers) {
        if (layers == null || layers.size() == 0) return;
        for (String layerId : layers) {
            Layer layer = LayerUtils.getLayer(mapboxStyle, layerId);
            if (layer != null) {
                layer.visibility(visible ? Visibility.VISIBLE : Visibility.NONE);
            }
        }
    }

    public void setLayerFilter(String layerId, Expression filter) {
        if(mapboxStyle==null)return;
        Layer layer = LayerUtils.getLayer(mapboxStyle, layerId);
        if (layer != null) {
            if (layer instanceof LineLayer) {
                ((LineLayer) layer).filter(filter);
            } else if (layer instanceof FillLayer) {
                ((FillLayer) layer).filter(filter);
            } else if (layer instanceof SymbolLayer) {
                ((SymbolLayer) layer).filter(filter);
            }
        }
    }

    /////////////////////////////////////////////////
    public void updateUserLocationMarkerPosition(Point point) {
        GeoJsonSource source = (GeoJsonSource) SourceUtils.
                getSource(mapboxStyle, LayerConstant.sourceOfUserLocation);
        Layer layer = LayerUtils.getLayer(mapboxStyle, LayerConstant.layerOfUserLocation);
        if (source != null && layer != null) {
            source.featureCollection(FeatureCollection.fromFeature(Feature.fromGeometry(point)));
//            SymbolLayer symbolLayer = (SymbolLayer) layer;
//            if (sensorData != null) {
//                symbolLayer.iconRotate(sensorData.getAngle());
//            }
        }
    }

    private void updateUserLocationMarkerRotate() {
        Layer layer = LayerUtils.getLayer(mapboxStyle, LayerConstant.layerOfUserLocation);
        if (layer != null) {
            SymbolLayer symbolLayer = (SymbolLayer) layer;
            symbolLayer.iconRotate(mapboxBearing+sensorData.getAngle());
        }
    }
    /////////////////////////////////////////////////
    private void addRasterSourceLayer(MapSource mapSource) {
        TileSet tileset = new TileSet.
                Builder("tileset" + mapSource.getSourceId(), mapSource.getTiles()).build();
        RasterSource rasterSource = new RasterSource.Builder(mapSource.getSourceId())
                .tileSet(tileset)
                .tileSize(mapSource.getTileSize() != null ? mapSource.getTileSize() : 256)
                .build();
        SourceUtils.addSource(mapboxStyle, rasterSource);
        if (mapSource.getLayers() != null && mapSource.getLayers().size() > 0) {
            for (MapLayer layer : mapSource.getLayers()) {
                RasterLayer rasterLayer = new RasterLayer(layer.getLayerId(), mapSource.getSourceId());
                if (!TextUtils.isEmpty(layer.getSourceLayer())) {
                    rasterLayer.sourceLayer(layer.getSourceLayer());
                }
                LayerUtils.addLayer(mapboxStyle, rasterLayer);
            }
        }
    }

    private void addVectorSourceLayer(MapSource mapSource) {
        TileSet tileset = new TileSet.Builder("tileset" + mapSource.getSourceId(),
                mapSource.getTiles()).build();
        VectorSource source = new VectorSource.Builder(mapSource.getSourceId())
                .tileSet(tileset)
                .build();
        SourceUtils.addSource(mapboxStyle, source);
        addLayerOfSource(mapSource);
    }

    public void updateGsonSourceData(String sourceId, FeatureCollection featureCollection) {
        Source source = SourceUtils.getSource(mapboxStyle, sourceId);
        if (source != null && (source instanceof GeoJsonSource)) {
            ((GeoJsonSource) source).featureCollection(featureCollection);
        }
    }

    public void addGsonLayer(MapSource mapSource) {
        try {
            GeoJsonSource.Builder builder = new GeoJsonSource.Builder(mapSource.getSourceId());
            //                .url("https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_50m_urban_areas.geojson")
            if(mapSource.getCluster()!=null&&mapSource.getCluster()){
                builder.cluster(true);
                builder.clusterMaxZoom(mapSource.getClusterMaxZoom());
                builder.clusterRadius(mapSource.getClusterRadius());
            }
            GeoJsonSource source = builder.build();
            if (mapSource.getGsonData() != null) {
                source.featureCollection(mapSource.getGsonData());
            } else if (mapSource.getUrl() != null && (mapSource.getUrl().startsWith("http://") || mapSource.getUrl().startsWith("https://"))) {
                source.url(mapSource.getUrl());
            } else if (mapSource.getFile() != null) {
                File file = new File(Utils.getMainPath(context), mapSource.getFile());
                String data = FileUtils.readFileToString(file, Charset.forName("UTF-8"));
                source.data(data);
            } else if (mapSource.getAssets() != null) {
                String data = FileUtils.readAssetFile(context, mapSource.getAssets());
                source.data(data);
            }
            SourceUtils.addSource(mapboxStyle, source);
            addLayerOfSource(mapSource);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    private void addLayerOfSource(MapSource mapSource) {
        if (mapSource == null || mapSource.getLayers() == null || mapSource.getLayers().size() == 0)
            return;
        for (MapLayer mapLayer : mapSource.getLayers()) {
            try {
                if (MapLayer.Type_line.equals(mapLayer.getType())) {
                    LineLayer layer = new LineLayer(mapLayer.getLayerId(), mapSource.getSourceId());
                    layer.lineCap(LineCap.ROUND);
                    layer.lineJoin(LineJoin.ROUND);
                    layer.lineColor(mapLayer.getPaint().getColor());//(Color.parseColor("#ff69b4"));
                    layer.lineWidth(mapLayer.getPaint().getWidth());
                    layer.lineOpacity(mapLayer.getPaint().getOpacity());
                    if (!TextUtils.isEmpty(mapLayer.getSourceLayer())) {
                        layer.sourceLayer(mapLayer.getSourceLayer());//chn_3  newxm
                    }
                    if (mapLayer.getFilter() != null) {
                        layer.filter(mapLayer.getFilter());
                    }
                    if (mapLayer.getMaxzoom() != null)
                        layer.maxZoom(mapLayer.getMaxzoom());
                    if (mapLayer.getMinzoom() != null)
                        layer.minZoom(mapLayer.getMinzoom());
                    LayerUtils.addLayer(mapboxStyle, layer);
                }
                else if (MapLayer.Type_fill.equals(mapLayer.getType())) {
                    FillLayer layer = new FillLayer(mapLayer.getLayerId(), mapSource.getSourceId());
                    if (mapLayer.getPaint() != null) {
                        if (mapLayer.getPaint().getColor() != null) {
                            layer.fillColor(mapLayer.getPaint().getColor());
                        }
                        if (mapLayer.getPaint().getOpacity() != null) {
                            layer.fillOpacity(mapLayer.getPaint().getOpacity());
                        }
                        if (mapLayer.getPaint().getOutlineColor() != null) {
                            layer.fillOutlineColor(mapLayer.getPaint().getOutlineColor());
                        }
                    }
                    if (!TextUtils.isEmpty(mapLayer.getSourceLayer())) {
                        layer.sourceLayer(mapLayer.getSourceLayer());//
                    }
                    if (mapLayer.getFilter() != null) {
                        layer.filter(mapLayer.getFilter());
                    }
                    if (mapLayer.getMaxzoom() != null)
                        layer.maxZoom(mapLayer.getMaxzoom());
                    if (mapLayer.getMinzoom() != null)
                        layer.minZoom(mapLayer.getMinzoom());
                    LayerUtils.addLayer(mapboxStyle, layer);
                }
                else if (MapLayer.Type_symbol.equals(mapLayer.getType())) {
                    SymbolLayer layer = new SymbolLayer(mapLayer.getLayerId(), mapSource.getSourceId());
                    layer.iconAllowOverlap(true);
                    MapLayerLayout layout = mapLayer.getLayout();
                    if (layout != null) {
                        if (layout.getImage() != null) {
                            layer.iconImage(layout.getImage());
                        }
                        if (layout.getSize() != null) {
                            layer.iconSize(layout.getSize());
                        }
                        if (layout.getOffset() != null) {
                            layer.iconOffset(layout.getOffset());
                        }
                        if (layout.getRotate() != null) {
                            layer.iconRotate(layout.getRotate());
                        }
                        if (layout.getAnchor() != null) {
                            layer.iconAnchor(layout.getAnchor());
                        }
                        if (layout.getTextField() != null) {
                            layer.textField(layout.getTextField());
                        }
                        if (layout.getTextFont() != null) {
                            layer.textFont(layout.getTextFont());
                        }
                        if (layout.getTextSize() != null) {
                            layer.textSize(layout.getTextSize());
                        }
                    }
                    if (mapLayer.getPaint() != null) {
                        if (mapLayer.getPaint().getColor() != null) {
                            layer.textColor(mapLayer.getPaint().getColor());
                        }
                    }
                    if (!TextUtils.isEmpty(mapLayer.getSourceLayer())) {
                        layer.sourceLayer(mapLayer.getSourceLayer());//
                    }
                    if (mapLayer.getFilter() != null) {
                        layer.filter(mapLayer.getFilter());
                    }
                    if (mapLayer.getMaxzoom() != null)
                        layer.maxZoom(mapLayer.getMaxzoom());
                    if (mapLayer.getMinzoom() != null)
                        layer.minZoom(mapLayer.getMinzoom());
                    LayerUtils.addLayer(mapboxStyle, layer);
                }else if (MapLayer.Type_circle.equals(mapLayer.getType())) {
                    CircleLayer layer = new CircleLayer(mapLayer.getLayerId(), mapSource.getSourceId());
                    MapLayerLayout layout = mapLayer.getLayout();
                    if (layout != null) {
                        if (layout.getColor() != null) {
                            layer.circleColor(layout.getColor());
                        }
                        if (layout.getSize() != null) {
                            layer.circleRadius(layout.getSize());
                        }
                    }
                    if (!TextUtils.isEmpty(mapLayer.getSourceLayer())) {
                        layer.sourceLayer(mapLayer.getSourceLayer());//
                    }
                    if (mapLayer.getFilter() != null) {
                        layer.filter(mapLayer.getFilter());
                    }
                    if (mapLayer.getMaxzoom() != null)
                        layer.maxZoom(mapLayer.getMaxzoom());
                    if (mapLayer.getMinzoom() != null)
                        layer.minZoom(mapLayer.getMinzoom());
                    LayerUtils.addLayer(mapboxStyle, layer);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    //////////////////////////////////////////////
    //Marker
    public View addMarkerView(Point point, int resId, int offsetY) {
        View markerView = viewAnnotationManager.addViewAnnotation(resId,    // view的layout id
                new ViewAnnotationOptions.Builder()
                        .geometry(point)
                        .offsetY(offsetY)
                        .allowOverlap(true)   // 允许markView重叠
                        .build());
        return markerView;
    }

    public void updateMaker(View markerView, Point point) {
        if (viewAnnotationManager != null) viewAnnotationManager.
                updateViewAnnotation(markerView, new ViewAnnotationOptions.Builder()
                        .geometry(Point.fromLngLat(point.longitude(), point.latitude()))
//                .offsetY(offsetY)
                        .allowOverlap(true)   // 允许markView重叠
                        .build());
    }

    public void removeMarker(View markerView) {
        if (viewAnnotationManager != null) viewAnnotationManager.removeViewAnnotation(markerView);
    }

    ////////////////////////////////////////////
    public Point getMapCenter() {
//        MapSnapshotInterface
        Point point = mapView.getMapboxMap().getCameraState().getCenter();
        return point;
    }
    //快照
    public Bitmap getSnapshot() {
//        MapSnapshotInterface
        Bitmap snapshot = mapView.snapshot();
        return snapshot;
    }

    public void getSnapshot(MapView.OnSnapshotReady onSnapshotReady) {
        mapView.snapshot(onSnapshotReady);
    }
    public void setIsDriving(boolean driving) {
        isDriving = driving;
    }

    public boolean isDriving() {
        return isDriving;
    }



    public void setMapBoxMarkerAddListener(MapBoxMarkerAddListener mapBoxMarkerAddListener) {
        this.mapBoxMarkerAddListener = mapBoxMarkerAddListener;
    }
    public void setOnMoveListener(OnMapMoveListener onMapMoveListener) {
        this.onMapMoveListener = onMapMoveListener;
    }
    public void addMapBoxCameraChangedListener(MapBoxCameraChangedListener listener) {
        if (cameraChangedListeners == null) {
            cameraChangedListeners = new ArrayList<>();
        }
        cameraChangedListeners.add(listener);
    }
    public void removeMapBoxCameraChangedListener(MapBoxCameraChangedListener listener) {
        if (cameraChangedListeners != null && listener != null) {
            for (MapBoxCameraChangedListener item : cameraChangedListeners) {
                if (item.getUuid().equals(listener.getUuid())) {
                    cameraChangedListeners.remove(item);
                }
            }
        }
    }
    public void setMapBoxViewListener(MapBoxViewListener mapBoxViewListener) {
        this.mapBoxViewListener = mapBoxViewListener;
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
    public interface MapBoxQueryListener {
        void onQuery(List<QueriedFeature> featureList);
    }

    public interface MapBoxMarkerAddListener {
        void onMarkerAdd(Point point);
    }

    public interface OnMapMoveListener {
        void onMoveStart(int zoom, Point point);
        void onMove(int zoom, Point point);
        void onMoveEnd(int zoom, Point point);
    }

    public interface MapBoxViewListener {
        void onMapStyleLoaded(Style style);
        void onLocationChange(LocationAddress location);
        void onZoomChange(Integer zoom);
        void onSensorChanged(SensorData sensorData);
        void onMapClicked(Point point);
        void onMapCenterChanged(Point point);
    }
}
